/**
 * 
 */
package xj.toolkit.fsm.tmpl;

import java.util.Arrays;
import java.util.Collection;

import org.apache.commons.beanutils.PropertyUtils;

import xj.toolkit.ebus.EventBus;
import xj.toolkit.fsm.DefaultFSMContextFactory;
import xj.toolkit.fsm.DefaultStateRepository;
import xj.toolkit.fsm.FSMUtils;
import xj.toolkit.fsm.FiniteStateMachine;
import xj.toolkit.fsm.State;
import xj.toolkit.fsm.predicate.TypeAcceptor;
import xj.toolkit.fsm.tmpl.state.StateAdapter;


/**
 * @author isdom
 *
 */
public class SimpleFSMProcessor {
	
	private	FiniteStateMachine		fsm;
	private	EventBus				eventBus;
	private	TemplateStatesFactory	factory = 
		new TemplateStatesFactory();
	
	/**
	 * @param template the template to set
	 */
	public void setTemplate(Object template) {
		factory.setTemplate(template);
	}

	/**
	 * @return the fsm
	 */
	public FiniteStateMachine getFsm() {
		return fsm;
	}

	/**
	 * @param templates
	 * @see xj.toolkit.fsm.tmpl.TemplateStatesFactory#setTemplateCollection(java.util.Collection)
	 */
	public void setTemplateCollection(Collection<Object> templates) {
		factory.setTemplateCollection(templates);
	}

	/**
	 * @param fsm the fsm to set
	 */
	public void setFsm(FiniteStateMachine fsm) {
		this.fsm = fsm;
	}

	/**
	 * @return the eventBus
	 */
	public EventBus getEventBus() {
		return eventBus;
	}

	/**
	 * @param eventBus the eventBus to set
	 */
	public void setEventBus(EventBus eventBus) {
		this.eventBus = eventBus;
	}

	public FiniteStateMachine process() throws Exception {
		State[] states = factory.createStates();
		
		if ( states.length > 0 ) {
			
			if ( PropertyUtils.isWriteable(fsm, "stateRepository") ) {
				DefaultStateRepository stateRepo = new DefaultStateRepository();
				stateRepo.setStates(Arrays.asList( states ) );
				PropertyUtils.setSimpleProperty(fsm, "stateRepository", stateRepo);
			}
			
			if ( PropertyUtils.isWriteable(fsm, "contextFactory") ) {
				
				DefaultFSMContextFactory ctxFactory = new DefaultFSMContextFactory();
				ctxFactory.setInitState( states[0]);
				ctxFactory.setEventBus(eventBus);
				
				PropertyUtils.setSimpleProperty(fsm, "contextFactory", ctxFactory);
			}
			
			if ( PropertyUtils.isWriteable(fsm, "initStateName") ) {
				
				PropertyUtils.setSimpleProperty(fsm, "initStateName", 
						FSMUtils.getStateNameOfInstance( states[0] ) );
			}
			
			if ( states[0] instanceof StateAdapter ) {
				StateAdapter stateAdapter = (StateAdapter)states[0];
				
				TypeAcceptor typeAcceptor  = new TypeAcceptor();
				
				typeAcceptor.setAllowTypes( 
						Arrays.asList( stateAdapter.getAcceptedEventTypes() ) );
				
				PropertyUtils.setSimpleProperty(fsm, "initeventAcceptor", typeAcceptor);
			}
		}
		
		return	fsm;
	}
}
